package com.gywj.race.util;

import org.apache.http.Consts;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * http请求客户端
 */
public class HttpClient {

    /**
     * 证书的路径
     */
    private static final String SSLCERT_PATH = "/home/weixin_cert/apiclient_cert.p12";
    /**
     * 证书的密钥
     */
    private static final String SSLCERT_PASSWORD = "1487537512";

    private String url;
    private Map<String, String> param;
    private int statusCode;
    private String content;
    private String xmlParam;
    private boolean isHttps;
    private boolean isSSL;
    private File file;
    private String description;
    private InputStream inputStream;

    public InputStream getInputStream() {
        return inputStream;
    }

    public void setInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    public boolean isHttps() {
        return isHttps;
    }

    public void setHttps(boolean isHttps) {
        this.isHttps = isHttps;
        this.isSSL = false;
    }

    public void setHttps(boolean isHttps, boolean isSSL) {
        this.isHttps = isHttps;
        this.isSSL = isSSL;
    }

    public String getXmlParam() {
        return xmlParam;
    }

    public void setXmlParam(String xmlParam) {
        this.xmlParam = xmlParam;
    }

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public HttpClient() {
    }

    public HttpClient(String url, Map<String, String> param) {
        this.url = url;
        this.param = param;
    }

    public HttpClient(String url, File file) {
        this.url = url;
        this.file = file;
    }

    public HttpClient(String url, File file, String description) {
        this.url = url;
        this.file = file;
        this.description = description;
    }

    public HttpClient(String url) {
        this.url = url;
    }

    public void setParameter(Map<String, String> map) {
        param = map;
    }

    public void addParameter(String key, String value) {
        if (param == null) {
            param = new HashMap<String, String>();
        }
        param.put(key, value);
    }

    public void post() throws IOException {
        HttpPost http = new HttpPost(url);
        setEntity(http);
        execute(http);
    }

    public void put() throws IOException {
        HttpPut http = new HttpPut(url);
        setEntity(http);
        execute(http);
    }

    public void get() throws IOException {
        if (param != null) {
            StringBuilder url = new StringBuilder(this.url);
            boolean isFirst = true;
            for (String key : param.keySet()) {
                if (isFirst) {
                    url.append("?");
                } else {
                    url.append("&");
                }
                url.append(key).append("=").append(param.get(key));
            }
            this.url = url.toString();
        }
        HttpGet http = new HttpGet(url);
        execute(http);
    }

    /**
     * set http post,put param
     */
    private void setEntity(HttpEntityEnclosingRequestBase http) {
        if (file != null || description != null) {
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
            if (file != null) {
                multipartEntityBuilder.addBinaryBody("media", file);
            }
            if (description != null) {
                multipartEntityBuilder.addTextBody("description", description,
                        ContentType.create("text/plain", Consts.UTF_8)
                );
            }
            HttpEntity entity = multipartEntityBuilder.build();
            http.setEntity(entity);
        }
        if (param != null) {
            List<NameValuePair> nvps = new LinkedList<NameValuePair>();
            for (String key : param.keySet()) {
                nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
            }
            http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
        }
        if (xmlParam != null) {
            http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
        }
    }

    private void execute(HttpUriRequest http) throws IOException {
        CloseableHttpClient httpClient = null;
        SSLContext sslcontext = null;
        try {
            if (isHttps) {

                if (isSSL) {
                    //注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
                    KeyStore keyStore = KeyStore.getInstance("PKCS12");
                    //默认密码是你的MCHID mch_id
                    keyStore.load(new FileInputStream(new File(SSLCERT_PATH)), SSLCERT_PASSWORD.toCharArray());

                    sslcontext = SSLContexts.custom()
                            .loadKeyMaterial(keyStore, SSLCERT_PASSWORD.toCharArray())
                            .build();
                } else {
                    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

                    sslcontext = SSLContexts.custom()
                            .loadTrustMaterial(keyStore, new TrustStrategy() {
                                // 信任所有
                                @Override
                                public boolean isTrusted(X509Certificate[] chain,
                                                         String authType)
                                        throws CertificateException {
                                    return true;
                                }
                            }).build();
                }
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslcontext);

                httpClient = HttpClients.custom()
                        .setSSLSocketFactory(sslsf)
                        .build();
            } else {
                httpClient = HttpClients.createDefault();
            }

            CloseableHttpResponse response = httpClient.execute(http);
            try {
                if (response != null) {
                    if (response.getStatusLine() != null) {
                        statusCode = response.getStatusLine().getStatusCode();
                    }
                    HttpEntity entity = response.getEntity();
                    HeaderElement[] elements = entity.getContentType().getElements();

                    if ("image/jpg".equals(elements[0].getName())) {
                        inputStream = entity.getContent();
                    } else {
                        // 响应内容
                        content = EntityUtils.toString(entity, Consts.UTF_8);
                    }
                }
            } finally {
                response.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpClient.close();
        }
    }

    public int getStatusCode() {
        return statusCode;
    }

    public String getContent() {
        return content;
    }

    /**
     * 获取地址inputStream流
     *
     * @param url
     * @return
     */
    public static InputStream sendHttpByGet(String url) {
        try {
            URL urlGet = new URL(url);
            HttpURLConnection urlConnection = (HttpURLConnection) urlGet.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.setConnectTimeout(20000);
            urlConnection.setReadTimeout(20000);
            return urlConnection.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
